package com.ys.chatserver.tool;

import cn.hutool.core.net.NetUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Objects;

public class IpAddressUtils {
    private static final Logger log = LoggerFactory.getLogger(IpAddressUtils.class);

    private static final String LOCAL_IP = "127.0.0.1";

    private static final String LOCAL_REMOTE_HOST = "0:0:0:0:0:0:0:1";


    public static Boolean isAndroid(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        return userAgent != null && userAgent.toLowerCase().contains("android");
    }

    /**
     * 获取本机ip
     *
     * @return ip
     */
    public static String getLocalIp() {
        String ip = "";
        if (isWindowsOs()) {
            try {
                ip = InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                log.error("获取ip地址异常");
            }
        } else {
            ip = getLinuxLocalIp();
        }
        return "".equals(ip) ? "127.0.0.1" : ip;
    }

    /**
     * 判断操作系统是否是Windows
     *
     * @return 操作系统是否是Windows
     */
    public static boolean isWindowsOs() {

        boolean isWindowsOs = false;
        String osName = System.getProperty("os.name");
        if (osName.toLowerCase().contains("windows")) {
            isWindowsOs = true;
        }
        return isWindowsOs;
    }

    /**
     * 获取Linux下的IP地址
     *
     * @return IP地址
     */
    private static String getLinuxLocalIp() {

        String ip = "";
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {

                NetworkInterface intf = en.nextElement();
                String name = intf.getName();
                if (!name.contains("docker") && !name.contains("lo")) {

                    ip = getRealIp(ip, intf);
                }
            }
        } catch (SocketException ex) {
            log.error("获取服务器ip地址异常");
        }
        return ip;
    }

    /**
     * 获取真实ip
     *
     * @param ip   ip
     * @param intf 网络接口
     * @return ip
     */
    private static String getRealIp(String ip, NetworkInterface intf) {
        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {

            InetAddress inetAddress = enumIpAddr.nextElement();
            if (!inetAddress.isLoopbackAddress()) {

                String ipaddress = inetAddress.getHostAddress();
                if (!ipaddress.contains("::") && !ipaddress.contains("0:0:") && !ipaddress.contains("fe80")) {
                    ip = ipaddress;
                }
            }
        }
        return ip;
    }

    /**
     * 获取客户端ip
     *
     * @param request servlet请求
     */
    public static String getIp(HttpServletRequest request) {
        if (Objects.isNull(request)) {
            return LOCAL_IP;
        } else {
            String remoteHost = getClientIp(request);
            remoteHost = StringUtils.strip(remoteHost, "[");
            remoteHost = StringUtils.strip(remoteHost, "]");
            return LOCAL_REMOTE_HOST.equals(remoteHost) ? LOCAL_IP : remoteHost;
        }
    }

    /**
     * 获取客户端IP
     *
     * <p>
     * 默认检测的Header:
     *
     * <pre>
     * 1、X-Forwarded-For
     * 2、X-Real-IP
     * 3、Proxy-Client-IP
     * 4、WL-Proxy-Client-IP
     * </pre>
     *
     * <p>
     * otherHeaderNames参数用于自定义检测的Header<br>
     * 需要注意的是，使用此方法获取的客户IP地址必须在Http服务器（例如Nginx）中配置头信息，否则容易造成IP伪造。
     * </p>
     *
     * @param request          请求对象{@link HttpServletRequest}
     * @param otherHeaderNames 其他自定义头文件，通常在Http服务器（例如Nginx）中配置
     * @return IP地址
     */
    public static String getClientIp(HttpServletRequest request, String... otherHeaderNames) {
        String[] headers = {"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
        if (ArrayUtils.isNotEmpty(otherHeaderNames)) {
            headers = ArrayUtils.addAll(headers, otherHeaderNames);
        }

        return getClientIpByHeader(request, headers);
    }


    /**
     * 获取客户端IP
     *
     * <p>
     * headerNames参数用于自定义检测的Header<br>
     * 需要注意的是，使用此方法获取的客户IP地址必须在Http服务器（例如Nginx）中配置头信息，否则容易造成IP伪造。
     * </p>
     *
     * @param request     请求对象{@link HttpServletRequest}
     * @param headerNames 自定义头，通常在Http服务器（例如Nginx）中配置
     * @return IP地址
     * @since 4.4.1
     */
    public static String getClientIpByHeader(HttpServletRequest request, String... headerNames) {
        String ip;
        for (String header : headerNames) {
            ip = request.getHeader(header);
            if (!NetUtil.isUnknown(ip)) {
                return NetUtil.getMultistageReverseProxyIp(ip);
            }
        }

        ip = request.getRemoteAddr();
        return NetUtil.getMultistageReverseProxyIp(ip);
    }

    /**
     * 根据ip地址定位
     *
     * @param request servlet请求
     */
    public static String getAddress(HttpServletRequest request) {

        String resultJson = "-";
        String ip = getIp(request);
        //如果是本地ip或局域网ip，则直接不查询
        if (StringUtils.isNotEmpty(ip)) {
            NetUtil.isInnerIP(ip);
        }

        return resultJson;
    }
}
